#include <map>
#include <iostream>
#include <unistd.h>
#include <opencv2/opencv.hpp>
#include "smartpipe.h"

using namespace std;
using namespace cv;
using namespace sp;

// 注册使用到的Function
void registe(){
    Image::Crop::cropWithInput::registe();
    Image::Gen::genFromMemory::registe();
    Image::Resize::resize::registe();
    Image::Save::markAndSave::registe();
    Model::Group::groupByBatch::registe();
    Model::Split::splitByShape::registe();
    Model::Trans::transferToDeviceMemory::registe();
    Model::Trans::transferToHostMemory::registe();
    Model::Yolo::yolo_preprocess::registe();
    Model::Yolo::yolo_inference::registe();
    Model::Yolo::yolo_postprocess::registe();
    Model::Retinanet::retinanet_preprocess::registe();
    Model::Retinanet::retinanet_inference::registe();
    Model::Retinanet::retinanet_postprocess::registe();
    Model::LPRnet::lprnet_preprocess::registe();
    Model::LPRnet::lprnet_inference::registe();
    Model::LPRnet::lprnet_postprocess::registe();
    Tool::Group::groupByRequestId::registe();
}

char* DATA_SOURCE;
char* DATA_TARGET;

/*
    初始化
    将视频流读入内存
*/
void init(){
    VideoCapture capture("/data/lx/SmartPipe/data_source/videos/0.mp4");
    long size = 800;
    Mat* data_source = new Mat[size];
    for(long i = 0; i < size; i++){
        cout << "load video: " << i << endl;
        Mat mat(2160, 3840, CV_8UC3);
        capture >> mat;
        memcpy(DATA_SOURCE + i*3840*2160*3, mat.datastart, 3840*2160*3);
    }
    capture.release();
}

/*
    将视频流写入磁盘
    结束释放资源
*/
void finish(){
    // 写入磁盘
    VideoWriter writer("/data/lx/SmartPipe/build/output.avi", VideoWriter::fourcc('M', 'J', 'P', 'G'), 30, Size(3840, 2160), true);
    long size = 800;
    for(long i = 0; i < size; i++){
        cout << "save video: " << i << endl;
        // 构建Mat对象，使其指向共享内存对应位置并写入。
        Mat mat(2160, 3840, CV_8UC3);
        mat.data = (uchar*)(DATA_TARGET + 3840*2160*3*i);
        mat.datastart = mat.data;
        mat.dataend = mat.datastart + 3840*2160*3;
        mat.datalimit = mat.dataend;
        writer << mat;
    }
    writer.release();
}

void test(SharedMemoryManager* smm, Gpu_SharedMemoryManager* gpu_smm){
    MDReader mdReader("/home/lx/SmartPipe/config/app9.md");
    auto Fs_table = mdReader.getFsTable();
    auto D_table = mdReader.getDeployTable();
    // App* app = new App(0, Fs_table, D_table, smm, gpu_smm);
    // app->init();
    // sleep(40);
    // app->run();
    // app->waitForComplete();
}

int main()
{
    cout << "pid: " << getpid() << endl;
    registe();
    SharedMemoryManager smm;
    Gpu_SharedMemoryManager gpu_smm;
    // 创建共享内存存储区，将输入输出视频都放在内存中
    SharedMemoryPool input_video_pool = smm.createSharedMemoryPool("input_video", Cv_Mat_Data_3840_2160_Memory, 800);
    SharedMemoryPool output_video_pool = smm.createSharedMemoryPool("output_video", Cv_Mat_Data_3840_2160_Memory, 800);
    DATA_SOURCE = input_video_pool.getDataPtr();
    DATA_TARGET = output_video_pool.getDataPtr();
    init();                // load video
    test(&smm, &gpu_smm);  // 运行测试
    smm.check();           // 检查是否存在内存泄露
    finish();              // save video
    return 0;
}